package cn.imatu.framework.sms.manager;

import cn.imatu.framework.exception.BizException;
import cn.imatu.framework.sms.manager.entity.AliyunSmsReps;
import cn.imatu.framework.sms.manager.entity.AliyunSmsReq;
import cn.imatu.framework.sms.properties.AliyunSmsProperties;
import com.alibaba.fastjson2.JSON;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author shenguangyang
 */
public class AliyunSmsManager implements ISmsManager<AliyunSmsReq, AliyunSmsReps> {
    private static final Logger log = LoggerFactory.getLogger(AliyunSmsManager.class);
    private static final String SUCCESS_CODE = "OK";
    private final AliyunSmsProperties aliyunSmsProperties;
    private Client client;

    public AliyunSmsManager(AliyunSmsProperties aliyunSmsProperties) {
        this.aliyunSmsProperties = aliyunSmsProperties;
        try {
            this.init();
        } catch (Exception e) {
            log.error("error: ", e);
            throw new BizException("初始aliyun sms client 失败");
        }
    }

    public void init() throws Exception {
        String accessKeySecret = this.aliyunSmsProperties.getAccessKeySecret();
        String accessKeyId = this.aliyunSmsProperties.getAccessKeyId();
        // 初始化client
        Config config = new Config().setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        this.client = new Client(config);
    }

    @Override
    public AliyunSmsReps send(AliyunSmsReq req) {
        req.check();
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                // 必填:短信签名-可在短信控制台中找到
                .setSignName(req.getSignName())
                // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
                // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
                // 参考：request.setTemplateParam("{\"变量1\":\"值1\",\"变量2\":\"值2\",\"变量3\":\"值3\"}")
                .setTemplateParam(JSON.toJSONString(req.getTemplateParam()))
                // 必填:短信模板-可在短信控制台中找到，发送国际/港澳台消息时，请使用国际/港澳台短信模版
                .setTemplateCode(req.getTemplateId())
                // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用，批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,
                // 验证码类型的短信推荐使用单条调用的方式；发送国际/港澳台消息时，接收号码格式为国际区号+号码，如“85200000000”
                .setPhoneNumbers(req.getPhoneNumbers())
                // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
                .setOutId(req.getOutId())
                // 可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段)
                .setSmsUpExtendCode(req.getSmsUpExtendCode());
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            SendSmsResponse response = client.sendSmsWithOptions(sendSmsRequest, runtime);
            SendSmsResponseBody responseBody = response.getBody();
            return AliyunSmsReps.builder()
                    .code(responseBody.getCode()).message(responseBody.getMessage())
                    .isSuccess(SUCCESS_CODE.equals(responseBody.getCode()))
                    .requestId(responseBody.getRequestId())
                    .build();
        } catch (TeaException e) {
            log.error("send sms fail, errorCode: {}, errorMessage: {}", e.getCode(), e.getMessage());
            return AliyunSmsReps.builder()
                    .code(e.getCode()).message(e.getMessage())
                    .isSuccess(false)
                    .requestId("-1").build();
        } catch (Exception e) {
            log.error("send sms fail, errorMessage: {}", e.getMessage());
            return AliyunSmsReps.builder()
                    .code("-1").message(e.getMessage())
                    .isSuccess(false)
                    .requestId("-1").build();
        }
    }
}
